package cn.yunsenlin.formula.cloud.group;

import cn.yunsenlin.formula.cloud.interfaces.GroupService;
import cn.yunsenlin.formula.cloud.mysql.bean.generator.TbGroup;
import cn.yunsenlin.formula.cloud.mysql.bean.generator.TbGroupCriteria;
import cn.yunsenlin.formula.cloud.mysql.bean.generator.TbResultCriteria;
import cn.yunsenlin.formula.cloud.mysql.mapper.generator.TbGroupMapper;
import cn.yunsenlin.formula.cloud.mysql.mapper.generator.TbResultMapper;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

@Service
public class GroupServiceImpl implements GroupService {
    private final TbGroupMapper tbGroupMapper;
    private final TbResultMapper tbResultMapper;

    @SuppressWarnings("all")
    public GroupServiceImpl(TbGroupMapper tbGroupMapper, TbResultMapper tbResultMapper) {
        this.tbGroupMapper = tbGroupMapper;
        this.tbResultMapper = tbResultMapper;
    }

    @Override
    public TbGroup addGroup(TbGroup tbGroup, int userId) {
        tbGroup.setUserId(userId);
        tbGroup.setRoot(false);
        tbGroupMapper.insert(tbGroup);
        return tbGroup;
    }

    @Override
    public void removeGroup(int id) {
        TbGroup tbGroupDB = tbGroupMapper.selectByPrimaryKey(id);
        if (!tbGroupDB.getRoot()) {
            List<TbGroup> sons = selectSonGroup(id);
            if (sons.size() > 0) {
                for (TbGroup tbGroup : sons) {
                    removeGroup(tbGroup.getId());
                }
            }
            tbGroupMapper.deleteByPrimaryKey(id);
        }
    }

    @Override
    public void updateGroup(TbGroup tbGroup) {
        if (updateGroupParentIdCheck(tbGroup)) {
            tbGroupMapper.updateByPrimaryKeySelective(tbGroup);
        }
    }

    public boolean updateGroupParentIdCheck(TbGroup tbGroup) {
        TbGroup tbGroupDB = tbGroupMapper.selectByPrimaryKey(tbGroup.getId());
        return tbGroup.getParentId().equals(tbGroupDB.getParentId()) ||
                !verifyAncestorRelation(tbGroupDB.getId(), tbGroup.getParentId());
    }

    @Override
    public boolean checkNameIsRepeat(String name, int groupId) {
        List<TbGroup> tbGroupList = selectSonGroup(groupId);
        for (TbGroup tbGroup : tbGroupList) {
            if(tbGroup.getName().equals(name)){
                return true;
            }
        }
        return false;
    }

    @Override
    public List<TbGroup> selectSonGroup(int id) {
        TbGroupCriteria criteria = new TbGroupCriteria();
        criteria.or().andParentIdEqualTo(id);
        return tbGroupMapper.selectByExample(criteria);
    }

    @Override
    public boolean verifyAncestorRelation(int father, int son) {
        TbGroup t = tbGroupMapper.selectByPrimaryKey(son);
        while (t != null && !t.getRoot()) {
            t = tbGroupMapper.selectByPrimaryKey(t.getParentId());
            if (t.getId().equals(father)) {
                return true;
            }
        }
        return false;
    }

    @Override
    public TbGroup selectRootGroup(Integer userId) {
        TbGroupCriteria criteria = new TbGroupCriteria();
        criteria.or().andRootEqualTo(true).andUserIdEqualTo(userId);
        return tbGroupMapper.selectByExample(criteria).get(0);
    }

    @Override
    public List<TbGroup> getChain(int id) {
        List<TbGroup> tbGroupList = new ArrayList<>();
        TbGroup n = tbGroupMapper.selectByPrimaryKey(id);
        tbGroupList.add(n);
        TbGroup i = n;
        while (!i.getRoot()){
            TbGroup c = tbGroupMapper.selectByPrimaryKey(i.getParentId());
            i = c;
            tbGroupList.add(c);
        }
        Collections.reverse(tbGroupList);
        return tbGroupList;
    }

    @Override
    public Integer getAmount(int id) {
        TbResultCriteria criteria = new TbResultCriteria();
        criteria.or().andGroupIdEqualTo(id);
        return tbResultMapper.countByExample(criteria);
    }
}
